Hellforge General Crackme III
by LazaRuS
Tutorial by Lucifer48 [Immortal Descendants]
(August 13th, 1999)
The crackme is coded in C++ builder, it's very similar as delphi (i asking myself which one is
the worse ?). There are a lot of garbage in the code, but the algo is easy.
A bpx hmemcpy allow us to enter in the code:
XXXX:004028ED CALL 004273E4 ;result: eax=length of name (we exit from here)
XXXX:004028F2 LEA EAX,[EBP-01DC]
XXXX:004028F8 CALL 0044DE94
XXXX:004028FD INC EAX ;length of name +1
XXXX:004028FE CMP EDI,EAX ;edi is the index of the loop
XXXX:00402900 LEA EAX,[EBP-01DC]
XXXX:00402906 SETL DL
XXXX:00402909 AND EDX,01
XXXX:0040290C PUSH EDX ;EDX=0 or EDX=1
...
XXXX:0040291A POP ECX
XXXX:0040291B TEST ECX,ECX ;if ECX=0, it is the end of the loop
XXXX:0040291D JNZ 0040285D ;back to the beginning of the loop
We are in the end of a loop. What is it doing ? In fact, it's very simple, it adds every ascii
value of each char of the name:
XXXX:004028A6 MOV EDX,[EBP-0234] ;index of loop
XXXX:004028AC ADD EDX,[EBP-01E0] ;add the address of the name
XXXX:00402AB2 DEC EDX
XXXX:00402AB3 MOVSX ECX,BYTE PTR [EDX] ;read one char (from the name)
XXXX:00402AB6 ADD [EBP-0230],ECX ;big add
Example: For my name (Lucifer48), i get:
4C + 75 + 63 + 69 + 66 + 65 + 72 + 34 + 38 = 336h
Just after the loop:
XXXX:00402923 IMUL EAX,[EBP-0230],000A2D77
XXXX:0040292D MOV [EBP-230],EAX ;save the result for the final comparison
We continue:
XXXX:004029A5 CMP EDI,EAX ;length of the two serials
XXXX:004029A7 LEA EAX,[EBP-01E8] ; edi: length of the first serial
XXXX:004029AD SETZ DL ; eax: length of the second serial
XXXX:004029B0 AND EDX,01
XXXX:004029B3 PUSH EDX
...
XXXX:004029D4 POP ECX
XXXX:004029D5 TEST CL,CL
XXXX:004029D7 JZ 00402B9C ;jump = the two serials haven't got the same size
Then, to go forward, we have to enter two serial of same length. We arrive now at the serial's loop;
here again, it is enornous, but what it is doing is easy:
XXXX:00402A41 MOV EDX,[EBP-023C] ;index of loop (k)
XXXX:00402A47 XOR EAX,EAX
XXXX:00402A49 ADD EDX,[EBP-01F0] ;address of first serial
XXXX:00402A4F DEC EDX
XXXX:00402A50 MOV CL,[EDX] ;read the k-th character of the serial
...
XXXX:00402A9A MOV EDX,[EBP-0240] ;index of loop (k)
XXXX:00402AA0 POP EAX ;AL= k-th character of the serial1
XXXX:00402AA1 ADD EDX,[EBP-01F4] ;address of second serial
XXXX:00402AA7 MOV ECX,0000000A
XXXX:00402AAC DEC EDX
XXXX:00402AAD XOR AL,[EDX] ;xor with the k-th character of serial2
XXXX:00402AAF MOVSX EAX,AL
XXXX:00402AB2 CDQ
XXXX:00402AB3 IDIV ECX
XXXX:00402AB5 MOVSX EDX,DL ;useless instruction
...
XXXX:00402B93 POP ECX ;ecx=0 or ecx=1
XXXX:00402B94 TEST ECX,ECX
XXXX:00402B96 JNZ 004029F2 ;if ecx=1 then the loop isn't finished
So, each result of mod will be kept and put together (with a proc similar as wfprintf). We arrive
now at the final comparison:
XXXX:00402BBF LEA EDX,[EBP-0200] ;d *edx: result of the name (what we must find)
XXXX:00402BC5 LEA EAX,[EBP-10] ;d *eax: code from the xor/mod (serial)
XXXX:00402BC8 CALL 0044DE7C ;comparison
XXXX:00402BCD PUSH EAX
...
XXXX:00402BE1 POP ECX
XXXX:00402BE2 TEST CL,CL
XXXX:00402BE4 JZ 00402C14 ;jmp = bad serials
This is the most simple registration (for me):
Name/ Lucifer48
Serial/ 548273178
Serial/ 000000000
or
Serial/ 548273179
Serial/ 000000001
...
Serial/ <=1;>:8>1
Serial/ 999999999
Taking numbers is the easiest way, because we don't care about the mod Ah result. Last one...
Name/ Lucifer48
Serial/ Lucifer48
Serial/ 15E516530
It is the end !
Greetings: All ID members (Volatility, Torn@do, ...), Eternal Bliss, ACiD BuRN,
Duelist, LaZaRuS, people on #cracking4newbies, french crackers, and other crackme makers.
(c) Lucifer48. All rights reversed